---
title: Contributing to code
sidebarTitle: Code
---

Code contributions are welcome! Whether you're fixing bugs, adding features, or improving performance, your contributions help deliver a better developer experience for everyone.

<Note>
    Before submitting large **new features or refactors**, please first discuss your ideas in [the forum](https://forum.langchain.com/). This ensures alignment with project goals and prevents duplicate work.

    This does not apply to bugfixes or small improvements, which you can contribute directly via pull requests. Be sure to link any relevant issues in your PR description. Use <Tooltip tip="(e.g. `Fixes #123`)">closing keywords</Tooltip> to automatically close issues when the PR is merged.

    New integrations should follow the [integration guidelines](/oss/contributing#add-a-new-integration).
</Note>

## Philosophy

Aim to follow these core principles for all code contributions:

<CardGroup cols={2}>
    <Card title="Backwards compatibility" icon="shield" href="#backwards-compatibility" arrow>
        Maintain stable public interfaces and avoid breaking changes
    </Card>

    <Card title="Testing first" icon="flask" href="#testing-requirements" arrow>
        Every change must include comprehensive tests to verify correctness and prevent regressions
    </Card>

    <Card title="Code quality" icon="star" href="#code-quality-standards" arrow>
        Follow consistent style, documentation, and architecture patterns
    </Card>

    <Card title="Security focus" icon="lock" href="#security-guidelines" arrow>
        Prioritize secure coding practices and vulnerability prevention
    </Card>
</CardGroup>

---

## Getting started

### Quick fix: submit a bugfix

For simple bugfixes, you can get started immediately:

<Steps>
    <Step title="Fork the repository">
        :::python
        Fork the [LangChain](https://github.com/langchain-ai/langchain) or [LangGraph](https://github.com/langchain-ai/langgraph) repo to your <Tooltip tip="If you fork to an organization account, maintainers will be unable to make edits.">personal GitHub account</Tooltip>
        :::
        :::js
        Fork the [LangChain](https://github.com/langchain-ai/langchainjs) or [LangGraph](https://github.com/langchain-ai/langgraphjs) repo to your personal GitHub account
        :::
    </Step>

    <Step title="Clone and setup">
        :::python

        ```bash
        git clone https://github.com/your-username/name-of-forked-repo.git

        # For instance, for LangChain:
        git clone https://github.com/parrot123/langchain.git

        # For LangGraph:
        git clone https://github.com/parrot123/langgraph.git
        ```

        ```bash
        # Inside your repo, install dependencies
        uv sync --all-groups
        ```
        :::
        :::js

        ```bash
        git clone https://github.com/your-username/name-of-forked-repo.git

        # For instance, for LangChain:
        git clone https://github.com/parrot123/langchainjs.git

        # For LangGraph:
        git clone https://github.com/parrot123/langgraphjs.git
        ```

        ```bash
        # Inside your repo, install dependencies
        pnpm install
        # Create a build for all packages to resolve workspace dependencies
        pnpm build
        ```
        :::
    </Step>

    <Step title="Create a branch">
        ```bash
        git checkout -b your-username/short-bugfix-name
        ```
    </Step>

    <Step title="Make your changes">
        Fix the bug while following our [code quality standards](#code-quality-standards)
    </Step>

    <Step title="Add tests">
        Include [unit tests](#test-writing-guidelines) that fail without your fix. This allows us to verify the bug is resolved and prevents regressions
    </Step>

    :::js
    <Step title="Run build">
        Run the build command to ensure the package still builds properly
        ```bash
        pnpm build
        # or build a specific workspace package
        pnpm --filter @langchain/core build
        ```
    </Step>
    :::

    <Step title="Run tests">
        Ensure all tests pass locally before submitting your PR

        :::python
        ```bash
        make lint
        make test

        # For bugfixes involving integrations, also run:
        make integration_tests
        ```
        :::
        :::js
        ```bash
        pnpm lint
        pnpm test

        # For bugfixes involving integrations, also run:
        pnpm test:int

        # Or run tests in a specific workspace package
        cd libs/langchain-core
        pnpm test
        pnpm lint

        # Or run tests for a specific package from the root of the repo
        pnpm --filter @langchain/core test
        pnpm --filter @langchain/core lint
        ```
        :::
    </Step>

    <Step title="Submit a pull request">
        Follow the PR template provided. If applicable, reference the issue you're fixing using a [closing keyword](https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword) (e.g. `Fixes #123`).
    </Step>
</Steps>

### Full development setup

For ongoing development or larger contributions:

<Steps>
    <Step title="Development environment">
        Set up your environment following our [setup guide](#development-environment)
    </Step>

    <Step title="Repository structure">
        Understand the [repository structure](#repository-structure) and package organization
    </Step>

    <Step title="Development workflow">
        Learn our [development workflow](#development-workflow) including testing and linting
    </Step>

    <Step title="Contribution guidelines">
        Review our [contribution guidelines](#contribution-guidelines) for features, bugfixes, and integrations
    </Step>
</Steps>

### Development environment

:::python
<Warning>
    Our Python projects use [`uv`](https://docs.astral.sh/uv/getting-started/installation/) for dependency management. Make sure you have the latest version of `uv` installed.
</Warning>
:::
:::js
<Warning>
    Our JS/TS projects uses [`pnpm`](https://pnpm.io/) for dependency management. Make sure you have the latest version of `pnpm` installed, or run `corepack enable` (on Node 24+) to setup the required pnpm version.
</Warning>
:::

Set up a development environment for the package(s) you're working on:

<Tabs>
    <Tab title="LangChain" icon="link">
        <AccordionGroup>
            <Accordion title="Core packages">
                For changes to `langchain-core`:

                :::python
                ```bash
                cd libs/core
                uv sync --all-groups
                make test  # Ensure tests pass before starting development
                ```
                :::
                :::js
                ```bash
                pnpm install
                # Run tests for a package from the package directory
                cd libs/langchain-core
                pnpm test

                # Or run tests for a package from the root of the repo
                pnpm --filter @langchain/core test

                ```
                :::
            </Accordion>

            <Accordion title="Main package">
                For changes to `langchain`:

                :::python
                ```bash
                cd libs/langchain
                uv sync --all-groups
                make test  # Ensure tests pass before starting development
                ```
                :::
                :::js
                ```bash
                pnpm install
                pnpm --filter langchain test  # Ensure tests pass before starting development
                ```
                :::
            </Accordion>

            :::python
            <Accordion title="Partner packages">
                For changes to [partner integrations](/oss/integrations/providers):

                ```bash
                cd libs/partners/langchain-{partner}
                make test  # Ensure tests pass before starting development
                ```
            </Accordion>
            :::
            :::js
            <Accordion title="Provider packages">
                For changes to [partner integrations](/oss/integrations/providers):

                ```bash
                pnpm install
                pnpm --filter @langchain/{provider} test  # Ensure tests pass before starting development
                ```
            </Accordion>
            :::
            :::python
            <Accordion title="Community packages">
                For changes to [community integrations](https://github.com/langchain-ai/langchain-community) (located in a separate repo):

                ```bash
                cd libs/community/langchain_community/path/to/integration
                make test  # Ensure tests pass before starting development
                ```
            </Accordion>
            :::
            :::js
            <Accordion title="Community packages">
                For changes to [community integrations](https://github.com/langchain-ai/langchainjs/tree/main/libs/langchain-community):

                ```bash
                pnpm install
                pnpm --filter @langchain/community test  # Ensure tests pass before starting development
                ```
            </Accordion>
            :::
        </AccordionGroup>
    </Tab>
    <Tab title="LangGraph" icon="circle-nodes">
        WIP - coming soon!
    </Tab>
</Tabs>

---

## Repository structure

<Tabs>
    <Tab title="LangChain" icon="link">
        LangChain is organized as a monorepo with multiple packages:

        <AccordionGroup>
            <Accordion title="Core packages" defaultOpen>
                :::python
                - **[`langchain-core`](https://github.com/langchain-ai/langchain/tree/master/libs/core#readme)** (located in `libs/core/`): Base interfaces and core abstractions
                - **[`langchain`](https://github.com/langchain-ai/langchain/tree/master/libs/langchain#readme)** (located in `libs/langchain/`): Main package with chains, agents, and retrieval logic
                :::
                :::js
                - **[`@langchain/core`](https://github.com/langchain-ai/langchainjs/tree/main/langchain-core#readme)** (located in `libs/langchain-core/`): Base interfaces and core abstractions
                - **[`langchain`](https://github.com/langchain-ai/langchainjs/tree/main/langchain#readme)** (located in `libs/langchain/`): Main package with chains, agents, and retrieval logic
                :::
            </Accordion>

            <Accordion title="Partner packages">

                :::python
                Located in `libs/partners/`, these are independently versioned packages for specific integrations. For example:
                - **[`langchain-openai`](https://github.com/langchain-ai/langchain/tree/master/libs/partners/openai#readme)**: [OpenAI](/oss/integrations/providers/openai) integrations
                - **[`langchain-anthropic`](https://github.com/langchain-ai/langchain/tree/master/libs/partners/anthropic#readme)**: [Anthropic](/oss/python/integrations/providers/anthropic) integrations
                - **[`langchain-google-genai`](https://github.com/langchain-ai/langchain-google/)**: [Google Generative AI](/oss/integrations/chat/google_generative_ai) integrations

                Many partner packages are in external repositories. Please check the [list of integrations](/oss/integrations/providers) for details.
                :::
                :::js
                Located in `libs/providers/`, these are independently versioned packages for specific integrations. For example:
                - **[`@langchain/openai`](https://github.com/langchain-ai/langchainjs/tree/main/libs/langchain-openai#readme)**: [OpenAI](/oss/integrations/providers/openai) integrations
                - **[`@langchain/anthropic`](https://github.com/langchain-ai/langchainjs/tree/main/libs/langchain-anthropic#readme)**: [Anthropic](oss/javascript/integrations/providers/anthropic) integrations
                - **[`@langchain/google-genai`](https://github.com/langchain-ai/langchainjs/tree/main/libs/langchain-google-genai#readme)**: [Google Generative AI](/oss/integrations/chat/google_generative_ai) integrations
                :::

            </Accordion>

            <Accordion title="Supporting packages">
                :::python
                - **[`langchain-text-splitters`](https://github.com/langchain-ai/langchain/tree/master/libs/text-splitters#readme)**: Text splitting utilities
                - **[`langchain-standard-tests`](https://github.com/langchain-ai/langchain/tree/master/libs/standard-tests#readme)**: Standard test suites for integrations
                - **[`langchain-cli`](https://github.com/langchain-ai/langchain/tree/master/libs/cli#readme)**: Command line interface
                - **[`langchain-community`](https://github.com/langchain-ai/langchain-community)**: Community maintained integrations (located in a separate repo)
                :::
                :::js
                - **[`@langchain/textsplitters`](https://github.com/langchain-ai/langchainjs/tree/main/libs/langchain-textsplitters#readme)**: Text splitting utilities
                - **[`@langchain/standard-tests`](https://github.com/langchain-ai/langchainjs/tree/main/libs/langchain-standard-tests#readme)**: Standard test suites for integrations
                - **[`langchain-community`](https://github.com/langchain-ai/langchainjs/tree/main/libs/langchain-community)**: Community maintained integrations
                :::

            </Accordion>
        </AccordionGroup>
    </Tab>
    <Tab title="LangGraph" icon="circle-nodes">
        WIP - coming soon!
    </Tab>
</Tabs>

---

## Development workflow

### Testing requirements

<Info>
    Directories are relative to the package you're working in.
</Info>

Every code change must include comprehensive tests.

<Steps>
    <Step title="Unit tests">
        :::python
        **Location**: `tests/unit_tests/`
        :::
        :::js
        **Location**: `src/tests/FILENAME_BEING_TESTED.test.ts`
        :::

        **Requirements**:
        - No network calls allowed
        - Test all code paths including edge cases
        - Use mocks for external dependencies

        :::python
        ```bash
        make test
        # Or directly:
        uv run --group test pytest tests/unit_tests
        ```
        :::
        :::js
        ```bash
        # Run the entire test suite
        pnpm test
        # Or run a specific test file
        pnpm test src/tests/FILENAME_BEING_TESTED.test.ts
        # Or run a specific test function
        pnpm test -t "the test that should be run"
        ```
        :::
    </Step>

    <Step title="Integration tests">
        Integration tests require access to external services/ provider APIs (which can cost money) and therefore are not run by default.

        Not every code change will require an integration test, but keep in mind that we'll require/ run integration tests separately as apart of our review process.

        :::python
        **Location**: `tests/integration_tests/`
        :::
        :::js
        **Location**: `src/tests/FILENAME_BEING_TESTED.int.test.ts`
        :::

        **Requirements**:
        - Test real integrations with external services
        - Use environment variables for API keys
        - Skip gracefully if credentials unavailable

        :::python
        ```bash
        make integration_tests
        ```
        :::
        :::js
        ```bash
        pnpm test:int
        ```
        :::
    </Step>

    <Step title="Test quality checklist">
        - Tests fail when your code is broken
        - Edge cases and error conditions are tested
        - Proper use of fixtures and mocks
    </Step>
</Steps>

### Code quality standards

Quality requirements:

<Tabs>
    <Tab title="Type hints">
        :::python
        **Required**: Complete type annotations for all functions

        ```python
        def process_documents(
            docs: list[Document],
            processor: DocumentProcessor,
            *,
            batch_size: int = 100
        ) -> ProcessingResult:
            """Process documents in batches.

            Args:
                docs: List of documents to process.
                processor: Document processing instance.
                batch_size: Number of documents per batch.

            Returns:
                Processing results with success/failure counts.
            """
        ```
        :::
        :::js
        **Required**: Complete types for all functions

        ```typescript
        function processDocuments(
            docs: Document[],
            processor: DocumentProcessor,
            batchSize: number = 100
        ): ProcessingResult {
            // ...
        }
        ```
        :::
    </Tab>

    <Tab title="Documentation">
        :::python
        **Required**: [Google-style docstrings](https://google.github.io/styleguide/pyguide.html) for all public functions
        :::
        :::js
        **Required**: [JSDocs](https://jsdoc.app/about-getting-started) for all exported functions and interfaces

        ```typescript
        /**
         * Document processing instance.
         */
        interface FooDocumentProcessor {
            /**
             * Process documents in batches.
             *
             * @param docs - List of documents to process.
             * @returns Processing results with success/failure counts.
             */
            process(docs: Document[]): ProcessingResult;
        }

        /**
         * Process documents in batches.
         *
         * @param docs - List of documents to process.
         * @param processor - Document processing instance.
         * @param batchSize - Number of documents per batch.
         * @returns Processing results with success/failure counts.
         */
        export function processDocuments(
            docs: Document[],
            processor: DocumentProcessor,
            batchSize: number = 100
        ): ProcessingResult {
            // ...
        }
        ```
        :::

        - Document all parameters and return values
        - Include usage examples for complex functions
        - Document raised exceptions
        - Focus on "why" rather than "what"
    </Tab>

    <Tab title="Code style">
        :::python
        **Automated**: Formatting and linting via [`ruff`](https://docs.astral.sh/ruff/)

        ```bash
        make format  # Apply formatting
        make lint    # Check style and types
        ```
        :::
        :::js
        **Automated**: Formatting and linting:

        ```bash
        pnpm lint    # Check style and types
        pnpm format  # Apply formatting
        ```
        :::

        **Standards**:
        - Descriptive variable names
        - Break up complex functions (aim for fewer than 20 lines)
        - Follow existing patterns in the codebase
    </Tab>
</Tabs>

:::python
### Manual formatting and linting

<Note>
    Code formatting and linting are enforced via CI/CD. Run these commands before committing to ensure your code passes checks.
</Note>

Run formatting and linting:

<Steps>
    <Step title="Format code">
        ```bash
        make format
        ```
    </Step>

    <Step title="Run linting checks">
        ```bash
        make lint
        ```
    </Step>

    <Step title="Verify changes">
        Both commands will show you any formatting or linting issues that need to be addressed before committing.
    </Step>
</Steps>
:::

---

## Contribution guidelines

### Backwards compatibility

<Warning>
    Breaking changes to public APIs are not allowed except for critical security fixes.

    See our [versioning policy](/oss/versioning) for details on major version releases.
</Warning>

Maintain compatibility:

<AccordionGroup>
    <Accordion title="Stable interfaces">
        **Always preserve**:
        - Function signatures and parameter names
        - Class interfaces and method names
        - Return value structure and types
        - Import paths for public APIs
    </Accordion>

    <Accordion title="Safe changes">
        **Acceptable modifications**:
        :::python
        - Adding new optional parameters
        :::
        :::js
        - Adding new optional parameters/type parameters
        :::
        - Adding new methods to classes
        - Improving performance without changing behavior
        - Adding new modules or functions
    </Accordion>

    <Accordion title="Before making changes">
        - **Would this break existing user code?**
        - Check if your target is public
        :::python
        - If needed, is it exported in `__init__.py`?
        :::
        - Are there existing usage patterns in tests?
    </Accordion>
</AccordionGroup>

### Bugfixes

For bugfix contributions:

<Steps>
    <Step title="Reproduce the issue">
        Create a minimal test case that demonstrates the bug. Maintainers and other contributors should be able to run this test and see the failure without additional setup or modification
    </Step>

    <Step title="Write failing tests">
        Add unit tests that would fail without your fix
    </Step>

    <Step title="Implement the fix">
        Make the **minimal change necessary** to resolve the issue
    </Step>

    <Step title="Verify the fix">
        Ensure that tests pass and no regressions are introduced
    </Step>

    <Step title="Document the change">
        Update docstrings if behavior changes, add comments for complex logic
    </Step>
</Steps>

### New features

We aim to keep the bar high for new features. We generally don't accept new core abstractions, changes to infra, changes to dependencies, or new agents/chains from outside contributors without an existing issue that demonstrates an acute need for them.

In general, feature contribution requirements include:

<Steps>
    <Step title="Design discussion">
        Open an issue describing:
        - The problem you're solving
        - Proposed API design
        - Expected usage patterns
    </Step>

    <Step title="Implementation">
        - Follow existing code patterns
        - Include comprehensive tests and documentation
        - Consider security implications
    </Step>

    <Step title="Integration considerations">
        - How does this interact with existing features?
        - Are there performance implications?
        - Does this introduce new dependencies?

        We will reject features that are likely to lead to security vulnerabilities or reports.
    </Step>
</Steps>

### Security guidelines

<Warning>
    Security is paramount. Never introduce vulnerabilities or unsafe patterns.
</Warning>

Security checklist:

<AccordionGroup>
    <Accordion title="Input validation">
        - Validate and sanitize all user inputs
        - Properly escape data in templates and queries
        :::python
        - Never use `eval()`, `exec()`, or `pickle` on user data, as this can lead to arbitrary code execution vulnerabilities
        :::
        :::js
        - Never use `eval()`, as this can lead to arbitrary code execution vulnerabilities
        :::
    </Accordion>

    <Accordion title="Error handling">
        - Use specific exception types
        - Don't expose sensitive information in error messages
        - Implement proper resource cleanup
    </Accordion>

    <Accordion title="Dependencies">
        - Avoid adding hard dependencies
        - Keep optional dependencies minimal
        - Review third-party packages for security issues
    </Accordion>
</AccordionGroup>

---

## Testing and validation

### Running tests locally

Before submitting your PR, ensure you have completed the following steps. Note that the requirements differ slightly between LangChain and LangGraph.

<Tabs>
    <Tab title="LangChain" icon="link">
        <Steps>
            <Step title="Unit tests">
                :::python

                ```bash
                make test
                ```
                :::
                :::js

                ```bash
                pnpm test
                ```
                :::
                All unit tests must pass
            </Step>

            <Step title="Integration tests">
                :::python

                ```bash
                make integration_tests
                ```
                :::
                :::js

                ```bash
                pnpm test:int
                ```
                :::
                (Run if your changes affect integrations)
            </Step>

            <Step title="Formatting">
                :::python

                ```bash
                make format
                make lint
                ```
                :::
                :::js

                ```bash
                pnpm format
                pnpm lint
                ```
                :::
                Code must pass all style checks
            </Step>

            :::python

            <Step title="Type checking">
                ```bash
                make type_check
                ```
                All type hints must be valid
            </Step>
            :::

            <Step title="PR submission">
                Push your branch and open a pull request. Follow the provided form template. Note related issues using a [closing keyword](https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword). After submitting, wait, and check to ensure the CI checks pass. If any checks fail, address the issues promptly - maintainers may close PRs that do not pass CI within a reasonable timeframe.
            </Step>
        </Steps>
    </Tab>
    <Tab title="LangGraph" icon="circle-nodes">
        WIP - coming soon!
    </Tab>
</Tabs>


### Test writing guidelines

In order to write effective tests, there's a few good practices to follow:

:::python
- Use natural language to describe the test in docstrings
- Use descriptive variable names
- Be exhaustive with assertions
:::
:::js
- Encapsulate the test in a `describe` block that describes the component being tested
- Use natural language to describe the test name
- Be exhaustive with assertions
- Only use snapshots for reasonably sized data objects
:::

<Tabs>
    <Tab title="Unit tests">
        :::python
        ```python
        def test_document_processor_handles_empty_input():
            """Test processor gracefully handles empty document list."""
            processor = DocumentProcessor()

            result = processor.process([])

            assert result.success
            assert result.processed_count == 0
            assert len(result.errors) == 0
        ```
        :::
        :::js
        ```typescript
        describe("DocumentProcessor", () => {
            it("Should handle empty document list", () => {
                const processor = new DocumentProcessor();
                const result = processor.process([]);

                expect(result.success).toBe(true);
                expect(result.processedCount).toBe(0);
                expect(result.errors).toHaveLength(0);
            });
        });
        ```
        :::
    </Tab>

    <Tab title="Integration tests">
        :::python
        ```python
        @pytest.mark.requires("openai")
        def test_openai_chat_integration():
            """Test OpenAI chat integration with real API."""

            chat = ChatOpenAI()
            response = chat.invoke("Hello")

            assert isinstance(response.content, str)
            assert len(response.content) > 0
        ```
        :::
        :::js
        ```typescript
        describe("ChatOpenAI", () => {
            it("Should test with real API", () => {
                const chat = new ChatOpenAI();
                const response = chat.invoke("Hello");
            });
        });
        ```
        :::
    </Tab>

    <Tab title="Mock usage">
        :::python
        ```python
        def test_retry_mechanism(mocker):
            """Test retry mechanism handles transient failures."""
            mock_client = mocker.Mock()
            mock_client.call.side_effect = [
                ConnectionError("Temporary failure"),
                {"result": "success"}
            ]

            service = APIService(client=mock_client)
            result = service.call_with_retry()

            assert result["result"] == "success"
            assert mock_client.call.call_count == 2
        ```
        :::
        :::js
        ```typescript
        describe("APIService", () => {
            it("Should call with retry", () => {
                const mockClient = new MockClient();
                const service = new APIService(client: mockClient);
                const result = service.callWithRetry();
            });
        });
        ```
        :::
    </Tab>
</Tabs>

## Getting help

Our goal is to have the simplest developer setup possible. Should you experience any difficulty getting setup, please ask in the [community slack](https://www.langchain.com/join-community) or open a [forum post](https://forum.langchain.com/).

<Check>
    You're now ready to contribute high-quality code to LangChain!
</Check>
